from datetime import datetime
from typing import Any, List, Optional

from pydantic import BaseModel, ConfigDict, Field, model_validator

from app.core.constants import ChangeType, ExecutionStatus, ExecutorType, TaskStatus, TriggerType
from app.utils.timezone import now


# ============================================
# 基础模型
# ============================================
class BaseJob(BaseModel):
    name: str = Field(..., description="任务名称")
    description: Optional[str] = Field(None, description="任务描述")
    executor_type: ExecutorType = Field(default=ExecutorType.MODULE, description="执行器类型")
    script_path: Optional[str] = Field(None, description="脚本路径")
    module_path: str = Field(..., description="模块路径，例如: apps.task.test.example_job")
    function_name: str = Field(..., description="函数名称，例如: example_job")
    trigger_type: TriggerType = Field(..., description="触发器类型")
    trigger_args: dict = Field(..., description="触发器参数 如: {'interval': 10}")
    args: Optional[list] = Field(None, description="函数参数 如: ['参数1', '参数2']")
    kwargs: Optional[dict] = Field(None, description="函数关键字参数")
    timeout: float = Field(default=60.0, description="超时时间(秒)")
    status: TaskStatus = Field(default=TaskStatus.ACTIVE, description="任务状态")
    priority: int = Field(default=0, description="优先级")
    creator_id: Optional[int] = Field(default=None, description="创建者ID")

    model_config = ConfigDict(from_attributes=True)


class BaseJobExecutionLog(BaseModel):
    job_id: int = Field(..., description="任务ID")
    status: ExecutionStatus = Field(default=ExecutionStatus.RUNNING, description="执行状态")
    result: Any = Field(None, description="执行结果")
    error_message: Optional[str] = Field(None, description="错误信息")
    traceback: Optional[str] = Field(None, description="错误堆栈")
    duration: float = Field(default=0.0, description="执行时长(秒)")

    start_time: datetime = Field(default_factory=now, description="开始执行时间")
    end_time: datetime = Field(default_factory=now, description="结束执行时间")

    model_config = ConfigDict(from_attributes=True)


class BaseJobChangeLog(BaseModel):
    job_id: int = Field(..., description="任务ID")
    change_type: ChangeType = Field(..., description="变更类型")
    changed_fields: dict = Field(..., description="变更的字段")
    operator: Optional[int] = Field(None, description="操作人ID")
    remark: Optional[str] = Field(None, description="备注")

    model_config = ConfigDict(from_attributes=True)


# ============================================
# Scheduler 中使用的模型
# ============================================
# 这是一个用于 Scheduler 的 Job 模型
class SchedulerJob(BaseJob):
    id: int = Field(..., description="任务ID")
    next_run_time: Optional[datetime] = None
    trigger: Any = None
    executor_type: ExecutorType = Field(default=ExecutorType.MODULE)

    @model_validator(mode="after")
    def init_trigger(self):
        try:
            from app.core.task.triggers import CronTrigger, DelayTrigger, IntervalTrigger

            trigger_map = {
                TriggerType.CRON.value: CronTrigger,
                TriggerType.DELAY.value: DelayTrigger,
                TriggerType.INTERVAL.value: IntervalTrigger,
            }

            trigger_cls = trigger_map.get(self.trigger_type)
            if trigger_cls:
                self.trigger = trigger_cls(**self.trigger_args)

        except Exception as e:
            raise ValueError(f"触发器初始化失败: {str(e)}")
        return self


class RedisJobExecutionResult(BaseJobExecutionLog):
    """
    没有 id 的预存在 Redis 中的执行结果模型
    """

    pass


# ============================================
# 接口中使用的模型
# ============================================
class JobItem(BaseJob):
    id: int


class JobChangeLog(BaseJobChangeLog):
    id: int = Field(..., description="变更记录ID")


class JobExecutionLog(BaseJobExecutionLog):
    id: int = Field(..., description="执行记录ID")


class JobCreate(BaseJob):
    pass


class JobUpdate(BaseJob):
    pass


class JobGet(JobItem):
    recent_logs: List[JobExecutionLog] = Field(default_factory=list, description="最近5条执行记录")
    change_logs: List[JobChangeLog] = Field(default_factory=list, description="最近5条变更记录")

    model_config = ConfigDict(from_attributes=True)


class JobListFilters(BaseModel):
    """任务列表过滤条件"""

    name: Optional[str] = None
    status: Optional[TaskStatus] = None
    creator_id: Optional[int] = None


class ExecutionHistoryFilters(BaseModel):
    """执行历史过滤条件"""

    job_id: Optional[str] = None
    status: Optional[str] = None
    executor: Optional[str] = None
    start_time: Optional[datetime] = None
    end_time: Optional[datetime] = None


class ChangeLogFilters(BaseModel):
    """变更记录过滤条件"""

    job_id: Optional[str] = None
    change_type: Optional[str] = None
    operator_id: Optional[int] = None
    start_time: Optional[datetime] = None
    end_time: Optional[datetime] = None
